package com.expmle.surfaceviewdemo

import android.content.Context
import android.graphics.*
import android.os.Build
import android.util.AttributeSet
import android.util.Log
import android.util.TypedValue
import android.view.SurfaceHolder
import android.view.SurfaceView
import kotlin.math.cos
import kotlin.math.min
import kotlin.math.sin
import kotlin.math.sqrt

/**
 * @Author: YuanPeikai
 * @CreateDate: 2020/6/23 15:57
 * @Description:
 */
class LuckyPan : SurfaceView, SurfaceHolder.Callback, Runnable {

    private var mHolder: SurfaceHolder? = null
    private var mCanvas: Canvas? = null;


    private lateinit var t: Thread;


    private var isRunning: Boolean = false;


    private val mStrs = arrayOf("单反相机", "IPAD", "恭喜发财", "IPHONE", "服装一套", "恭喜发财")


    private val mImags =
        arrayOf(
            R.mipmap.danfan,
            R.mipmap.ipad,
            R.mipmap.f015,
            R.mipmap.iphone,
            R.mipmap.meizi,
            R.mipmap.f015
        );

    private lateinit var mImagsBitmap: Array<Bitmap?>

    private val mColors =
        arrayOf(
            Color.BLUE,
            Color.GREEN,
            Color.BLUE,
            Color.GREEN,
            Color.BLUE,
            Color.GREEN
        )


    private var mItemCount = 6;


    private var mRange: RectF = RectF();


    private var mRadius = 0f;


    private lateinit var mArcPaint: Paint;

    private lateinit var mTextPaint: Paint;


    private var mSpeed = 0f;

    @Volatile
    private var mStartAngle = 0f;

    private var isShouldEnd = false;

    private var mCenter = 0f;

    private var mPadding = 0f;


    private var mBgBitmap: Bitmap = BitmapFactory.decodeResource(resources, R.mipmap.bg2);

    private var mTextSize: Float =
        TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 20f, resources.displayMetrics)


    constructor(context: Context?) : this(context, null)


    constructor(context: Context?, attrs: AttributeSet?) : this(context, attrs, 0)


    constructor(
        context: Context?,
        attrs: AttributeSet?,
        defStyleAttr: Int
    ) : super(context, attrs, defStyleAttr) {

        mHolder = holder;
        mHolder!!.addCallback(this);

        isFocusable = true;
        isFocusableInTouchMode = true;
        keepScreenOn = true;

    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)

        val width = min(measuredWidth, measuredHeight)

        mPadding = paddingLeft.toFloat();
        mRadius = width - mPadding * 2;
        mCenter = (width / 2).toFloat();
        setMeasuredDimension(width, width)
    }

    override fun surfaceChanged(holder: SurfaceHolder?, format: Int, width: Int, height: Int) {
        println("LuckyPan.surfaceChanged")
    }

    override fun surfaceDestroyed(holder: SurfaceHolder?) {
        println("LuckyPan.surfaceDestroyed")
        isRunning = false;
    }

    override fun surfaceCreated(holder: SurfaceHolder?) {
        println("LuckyPan.surfaceCreated")

        mArcPaint = Paint();
        mArcPaint.isAntiAlias = true;
        mArcPaint.isDither = true;


        mTextPaint = Paint();
        mTextPaint.setColor(Color.WHITE);
        mTextPaint.textSize = mTextSize;


        mRange = RectF(mPadding, mPadding, mPadding + mRadius, mPadding + mRadius)

        mImagsBitmap = arrayOfNulls(mItemCount)

        for (i in 0 until mItemCount) {
            mImagsBitmap!![i] = BitmapFactory.decodeResource(resources, mImags[i])
        }


        isRunning = true;
        t = Thread(this)
        t.start()

    }

    override fun run() {


        while (isRunning) {
            val start = System.currentTimeMillis()
            draw();
            val end = System.currentTimeMillis()
            if (end - start < 50) {
                try {
                    Thread.sleep(50 - (end - start))
                } catch (e: InterruptedException) {
                    e.printStackTrace()
                }
            }
        }


    }

    private fun draw() {
        try {
            mCanvas = mHolder!!.lockCanvas();
            if (mCanvas != null) {
                drawBg();

                var tmpAngle: Float = mStartAngle;

                var sweepAngle: Float = (360 / mItemCount).toFloat();

                for (i in 0 until mItemCount) {
                    mArcPaint.setColor(mColors[i])
                    mCanvas!!.drawArc(mRange, tmpAngle, sweepAngle, true, mArcPaint)

                    drawText(tmpAngle, sweepAngle, mStrs[i]);

                    drawIcon(tmpAngle, mImagsBitmap[i]);


                    tmpAngle += sweepAngle

                }

                mStartAngle += mSpeed;

                if (isShouldEnd) {
                    mSpeed -= 1;
                }
                if (mSpeed <= 0) {
                    mSpeed = 0f;
                    isShouldEnd = false;
                }


            }

        } catch (e: Exception) {
            mCanvas = null;
            e.printStackTrace()

        } finally {
            if (mCanvas != null) {
                mHolder!!.unlockCanvasAndPost(mCanvas)
            }
        }


    }


    public fun luckyStart(index: Int) {


        val angle: Int = 360 / mItemCount;


        val from: Float = (270 - (index + 1) * angle).toFloat();
        val end: Float = from + angle;

        //设置停下来需要旋转的距离,这里加5和减5的作用是，避免出现指针出现压边的情况。
        val targetFrom: Float = 4 * 360 + from + 5;
        val targetEnd = 4 * 360 + end - 5;

        val v1: Float = (-1 + sqrt(1 + 8 * targetFrom)) / 2
        val v2: Float = (-1 + sqrt(1 + 8 * targetEnd)) / 2

        mSpeed = (v1 + Math.random() * (v2 - v1)).toFloat()





        isShouldEnd = false;
    }

    public fun luckyEnd() {
        mStartAngle = 0f;
        isShouldEnd = true;
    }

    public fun isStart(): Boolean {
        return mSpeed != 0f;
    }

    public fun isShouldEnd(): Boolean {
        return isShouldEnd;
    }


    private fun drawIcon(tmpAngle: Float, bitmap: Bitmap?) {

        val imgWidth = (mRadius / 8).toInt();
        val angle = ((tmpAngle + 360 / mItemCount / 2) * Math.PI / 180)

        val x = (mCenter + mRadius / 2 / 2 * cos(angle)).toInt()
        val y = (mCenter + mRadius / 2 / 2 * sin(angle)).toInt()

        val rect: Rect =
            Rect(x - imgWidth / 2, y - imgWidth / 2, x + imgWidth / 2, y + imgWidth / 2);
        mCanvas!!.drawBitmap(bitmap!!, null, rect, null)
    }

    private fun drawText(tmpAngle: Float, sweepAngle: Float, s: String) {

        val path = Path();
        path.addArc(mRange, tmpAngle, sweepAngle)

        val textWidht = mTextPaint.measureText(s)
        val hOffset = (mRadius * Math.PI / mItemCount / 2 - textWidht / 2).toFloat();




        mCanvas!!.drawTextOnPath(s, path, hOffset, 80f, mTextPaint)


    }

    private fun drawBg() {


        mCanvas!!.drawColor(Color.WHITE)


        mCanvas!!.drawBitmap(
            mBgBitmap,
            null,
            Rect(
                (mPadding / 2).toInt(),
                (mPadding / 2).toInt(),
                (measuredWidth - mPadding / 2).toInt(),
                (measuredHeight - mPadding / 2).toInt()
            ),
            null
        )


    }


}